package com.example.nfc.server.network.eventbus;

import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.SystemClock;

/**
 * Create by 游德禄 on 2019-9-25
 */
final class HandlerPoster extends Handler {
    private final PendingPostQueue queue;
    private final int maxMillisInsideHandleMessage;
    private final EventBus eventBus;
    private boolean handlerActive;

    HandlerPoster(EventBus eventBus, Looper looper, int maxMillisInsideHandleMessage) {
        super(looper);
        this.eventBus = eventBus;
        this.maxMillisInsideHandleMessage = maxMillisInsideHandleMessage;
        this.queue = new PendingPostQueue();
    }

    void enqueue(Subscription subscription, Object event) {
        PendingPost pendingPost = PendingPost.obtainPendingPost(subscription, event);
        synchronized(this) {
            this.queue.enqueue(pendingPost);
            if (!this.handlerActive) {
                this.handlerActive = true;
                if (!this.sendMessage(this.obtainMessage())) {
                    throw new EventBusException("Could not send handler message");
                }
            }

        }
    }

    public void handleMessage(Message msg) {
        boolean rescheduled = false;

        try {
            long started = SystemClock.uptimeMillis();

            long timeInMethod;
            do {
                PendingPost pendingPost = this.queue.poll();
                if (pendingPost == null) {
                    synchronized(this) {
                        pendingPost = this.queue.poll();
                        if (pendingPost == null) {
                            this.handlerActive = false;
                            return;
                        }
                    }
                }

                this.eventBus.invokeSubscriber(pendingPost);
                timeInMethod = SystemClock.uptimeMillis() - started;
            } while(timeInMethod < (long)this.maxMillisInsideHandleMessage);

            if (!this.sendMessage(this.obtainMessage())) {
                throw new EventBusException("Could not send handler message");
            } else {
                rescheduled = true;
            }
        } finally {
            this.handlerActive = rescheduled;
        }
    }
}

